home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 020a / dcfg202.zip / DCFGT.PAS < prev    next >
Pascal/Delphi Source File  |  1992-01-01  |  13KB  |  426 lines

  1.  
  2. {Dirt Cheap Frame Grabber V2.00T (Text version)}
  3. {as of 1 January 1992 - by Michael Day}
  4. {public domain}
  5.  
  6. program DCFGT;
  7. uses crt;
  8. const maxframe = 30000;
  9.       maxintrp = 30000;
  10.  
  11. type frametype = array[0..maxframe] of byte;
  12.      frameptr = ^frametype;
  13.      intrptype = array[0..maxintrp] of byte;
  14.      intrpptr = ^intrptype;
  15.      string8 = string[8];
  16.  
  17.      FrameObj = object
  18.        fary : array[0..3] of frameptr;
  19.        iary : intrpptr;
  20.        inport : word;      {frame port data input address (video data)}
  21.        outport : word;     {frame port data output address (control)}
  22.        frameport : word;   {printer port number to use for frame grabber}
  23.        grabsize : word;    {size of data to grab from port}
  24.        framenum : byte;    {frame sequence number}
  25.        IntrpWidth : word;  {width of the intrp array (scan width) }
  26.        IntrpSize : word;   {size of the intrp array (width*lines) }
  27.  
  28.        constructor Init;
  29.        destructor Done;
  30.        procedure SetFramePort(what:string8);
  31.        function  GrabFrame(inprt,size:word; Fptr:frameptr):boolean;
  32.        function  GrabOne:boolean;
  33.        procedure F2IConvert(Fnum:byte; GSize,IWidth,ISize:word;
  34.                             Iptr:IntrpPtr; Fptr:FramePtr);
  35.      end;
  36.  
  37. var  Frame : FrameObj;
  38.      prnarray : array[0..3] of word absolute $40:$08;
  39.  
  40.      crtmode : byte absolute $40:$49;
  41.      oldmode : byte;
  42.      i:word;
  43.      ib:byte;
  44.      cx:char;
  45.  
  46.  
  47. {-----------------------------------------------------------}
  48. {     gray level interpretation chart                       }
  49. {                                                           }
  50. {          frame data                                       }
  51. {gray    F3  F2  F1  F0   F3 = frame 3, F2 = frame 2        }
  52. {level:  76  54  32  10   F1 = frame 1, F0 = frame 0        }
  53. {   12:  11  xx  xx  xx   each group of two bits            }
  54. {   11: <11  11  xx  xx   represent the video level         }
  55. {   10: <11 <11  11  xx   for the frame indicated           }
  56. {    9: <11 <11 <11  11                                     }
  57. {    8:  10 <11 <11 <11   xx = any bit pattern              }
  58. {    7: <10  10 <11 <11   <11 = less than 11; (10, 01, 00)  }
  59. {    6: <10 <10  10 <11   <10 = less than 10; (01 or 00)    }
  60. {    5: <10 <10 <10  10   11, 10, 01, or 00 = the indicated }
  61. {    4:  01 <10 <10 <10                absolute bit pattern }
  62. {    3:  00  01 <10 <10                                     }
  63. {    2:  00  00  01 <10   the gray level for the specified  }
  64. {    1:  00  00  00  01   bit pattern is shown at the left  }
  65. {    0:  00  00  00  00                                     }
  66. {-----------------------------------------------------------}
  67. {this array is used to translate from the interpretation    }
  68. {array data into a gray level for display on the screen     }
  69. const IntrpXlat : array[0..255] of byte = (
  70.     0,1,5,9,2,2,5,9,         6,6,6,9,10,10,10,10,
  71.     3,3,5,9,3,3,5,9,         6,6,6,9,10,10,10,10,
  72.     7,7,7,9,7,7,7,9,         7,7,7,9,10,10,10,10,
  73.     11,11,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,
  74.     4,4,5,9,4,4,5,9,         6,6,6,9,10,10,10,10,
  75.     4,4,5,9,4,4,5,9,         6,6,6,9,10,10,10,10,
  76.     7,7,7,9,7,7,7,9,         7,7,7,9,10,10,10,10,
  77.     11,11,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,
  78.     8,8,8,9,8,8,8,9,         8,8,8,9,10,10,10,10,
  79.     8,8,8,9,8,8,8,9,         8,8,8,9,10,10,10,10,
  80.     8,8,8,9,8,8,8,9,         8,8,8,9,10,10,10,10,
  81.     11,11,11,11,11,11,11,11, 11,11,11,11,11,11,11,11,
  82.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,
  83.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,
  84.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12,
  85.     12,12,12,12,12,12,12,12, 12,12,12,12,12,12,12,12);
  86.  
  87. {-----------------------------------------------------------}
  88.  
  89.  
  90.     {grab a chunk of video from inprt size bytes in length into fary}
  91.     function FrameObj.GrabFrame(inprt,size:word; Fptr:frameptr):boolean; assembler;
  92.      asm
  93.       mov bx,17000      {timeout if we go over 50ms without sync}
  94.       mov dx,[inprt]
  95.       les di,[Fptr]     {now collect a frame}
  96.       mov cx,0
  97.  
  98.      @vsloop1:
  99.       mov ah,8 {[vsyncslice]}  {if we are in a vert sync, get out of it first}
  100.      @vsloop2:
  101.       dec bx
  102.       jz @vdone
  103.       in al,dx
  104.       shl al,1
  105.       jc @vsloop1
  106.       dec ah
  107.       jnz @vsloop2
  108.  
  109.      @vsloop3:
  110.       mov ah,8 {[vsyncslice]}  {find the start of a vert sync}
  111.      @vsloop4:
  112.       dec bx
  113.       jz @vdone
  114.       in al,dx
  115.       shl al,1
  116.       jnc @vsloop3
  117.       dec ah
  118.       jnz @vsloop4
  119.  
  120.       mov cx,[size]      {start collecting data}
  121.       rep
  122.       db 6ch
  123.  
  124.      @vdone:
  125.       xor al,al        {return error code}
  126.       or bh,bl         {one = all ok}
  127.       jz @vexit        {zero = no sync}
  128.       inc al
  129.      @vexit:
  130.     end;
  131.  
  132.  
  133.   Constructor FrameObj.Init;
  134.   var i:byte;
  135.   begin
  136.  
  137.     for i := 0 to 3 do
  138.     begin
  139.       new(fary[i]);
  140.       fillchar(fary[i]^,sizeof(fary[i]^),0);
  141.     end;
  142.     new(iary);
  143.     fillchar(iary^,sizeof(iary^),0);
  144.     move(IntrpXlat,iary^,256);
  145.   end;
  146.  
  147.  
  148.   Destructor FrameObj.Done;
  149.   begin
  150.   end;
  151.  
  152.  
  153.   procedure FrameObj.SetFramePort(what:string8);
  154.   begin
  155.     frameport := 0;
  156.     if length(what) > 0 then
  157.     begin
  158.       case what[1] of
  159.        '2': frameport := 1;
  160.        '3': frameport := 2;
  161.        '4': frameport := 3;
  162.       end;
  163.     end;
  164.     outport := prnarray[frameport]; {- $378}  {get port base addr}
  165.     inport := outport+1;    {- $379}
  166.  
  167.     port[outport+2] := $04; {- $37A}   {init output control lines}
  168.     port[outport] := $ff;    {init data lines}
  169.     grabsize := 20000;           {default grab size}
  170.     framenum := 0;
  171.     IntrpWidth := 40;
  172.     IntrpSize := IntrpWidth*(262-12);
  173.    end;
  174.  
  175.  
  176.  
  177.   function FrameObj.GrabOne:boolean;
  178.   var Fptr : framePtr;
  179.   begin
  180.     inc(framenum);
  181.     framenum := framenum and 3;
  182.     port[frame.outport] := (framenum shl 6) or $3f;
  183.     Fptr := fary[framenum];
  184.     asm CLI; end;
  185.     GrabOne := GrabFrame(inport,grabsize,Fptr);
  186.     asm STI; end;
  187.     port[frame.outport] := $3f;
  188.   end;
  189.  
  190.  
  191.  
  192. {=====================================================================}
  193.    {now we are gonna display the video on the screen}
  194.    procedure IntrpDisplay(fnum,IWidth,ISize:word; Iptr:IntrpPtr);
  195.    var Bottom:word;
  196.    begin
  197.      asm
  198.        push ds
  199.        lds si,ss:[Iptr]      {get intrp array pointer}
  200.        mov bx,si             {point bx at the start of the array}
  201.        add si,256            {first 256 bytes has intpr array}
  202.        mov ax,ss:[ISize]     {compute intrp bottom address offset}
  203.        add ax,si
  204.        mov ss:[Bottom],ax    {and save it}
  205.        mov ax,0B800h         {point es to the display segment}
  206.        mov es,ax
  207.        mov cx,ss:[IWidth]    {put intrp right edge offset}
  208.        add si,cx
  209.        add si,cx
  210.        add si,cx
  211.        add si,cx
  212.        add si,cx
  213.        add si,cx
  214.        add si,cx
  215.        add si,cx
  216.        add si,cx
  217.        add si,cx
  218.        add si,cx
  219.        add si,cx
  220.        add si,cx
  221.        add si,cx
  222.  
  223.        mov di,fnum           {start at top left corner of screen}
  224.        and di,2              {offset by frame number count (even/odd)}
  225.  
  226.      @dlp1:
  227.        push di
  228.      @dlp2:
  229.        lodsb          {get a intrp byte}
  230.        xlat           {translate it to gray scale number}
  231.        push bx
  232.        mov ah,al
  233.        lea bx,@ahxlat
  234.        segcs
  235.        xlat
  236.        xchg ah,al
  237.        lea bx,@alxlat
  238.        segcs
  239.        xlat
  240.        pop bx
  241.  
  242.        and di,$fffe
  243.        stosw          {display it}
  244.       { stosw }         {display it}
  245.        inc di
  246.        inc di         {skip a display pixel (we get it next time)}
  247.        dec cx         {end of the scan line?}
  248.        jnz @dlp2      {loop until done}
  249.        pop di         {restore original display start offset}
  250.        add di,160     {add display width to it}
  251.  
  252.        mov cx,ss:[IWidth]  {restore Iwidth to cx}
  253.        add si,cx           {skip three video scan lines}
  254.        add si,cx
  255.        add si,cx           {skip three video scan lines}
  256.        add si,cx
  257.        add si,cx           {skip three video scan lines}
  258.        add si,cx
  259.        add si,cx
  260.        add si,cx           {skip three video scan lines}
  261.        add si,cx
  262.        cmp si,ss:[Bottom]  {are we at the bottom?}
  263.        jc @dlp1            {keep going if not}
  264.        jmp @done
  265.  
  266.      @alxlat: db 32,176,177,178,219,176,177,178,219,176,177,178,219
  267.      @ahxlat: db 7,8,8,8,8,7,7,7,7,15,15,15,15
  268.  
  269.      @done:
  270.        pop ds          {ok, we're done}
  271.      end;
  272.    end;
  273.  
  274.  
  275.  
  276.    {==================================================================}
  277.  
  278.  
  279.    {------------------------------------------------------------------}
  280.    {note: this assumes that the frame grab array has been preformated}
  281.    {with starting with a valid scan line at the top of the screen}
  282.    procedure FrameObj.F2Iconvert(Fnum:byte; GSize,IWidth,ISize:word;
  283.                                  Iptr:IntrpPtr; Fptr:FramePtr);
  284.    var Bottom:word;
  285.    begin
  286.      asm
  287.        mov cl,ss:[Fnum]      {get gray scale frame number}
  288.        and cl,03H
  289.        add cl,cl             {*2 = shifter count}
  290.        mov ch,0FCH           {create intrp data mask}
  291.        rol ch,cl
  292.        mov dx,ss:[GSize]     {get size of grabbed data to convert}
  293.        inc dx
  294.        les di,ss:[Iptr]      {get intrp array pointer}
  295.        add di,256            {first 256 bytes has xlat array}
  296.        mov ax,di
  297.        add ax,ss:[ISize]     {compute intrp bottom address offset}
  298.        mov ss:[Bottom],ax    {and save it}
  299.        mov bx,ss:[IWidth]    {put intrp right edge offset into bx}
  300.  
  301.        push ds               {save current data segment}
  302.        lds si,ss:[Fptr]      {get video frame pointer to DS:SI}
  303.  
  304.      {data conversion loop starts here}
  305.      @loop1:
  306.        dec dx           {did we run out of data?}
  307.        jz @done
  308.        lodsb            {get a frame scan byte}
  309.        shl al,1         {if it is a sync, try again}
  310.        jc @loop1
  311.  
  312.      @loop2:
  313.        dec dx           {did we run out of data?}
  314.        jz @done
  315.        lodsb            {get a frame scan byte}
  316.        shl al,1         {if it is a sync, we are}
  317.        jc @loop4        {done with the scan line}
  318.  
  319.        {convert scan input data to intrp level reference}
  320.        xor ah,ah        {init to zero level}
  321.        shl al,1         {if highest level on}
  322.        adc ah,0         {add one to level count}
  323.        shl al,1         {if next high level on}
  324.        adc ah,0         {add one to level count}
  325.        shl al,1         {if lowest level on}
  326.        adc ah,0         {add one to level count}
  327.        shl ah,cl        {adjust result to position}
  328.        mov al,es:[di]   {get current intrp value}
  329.        and al,ch        {strip old intrp value}
  330.        or al,ah         {insert new intrp value}
  331.        mov es:[di],al   {save the new intrp value}
  332.        inc di
  333.        dec bx           {if not at end of intrp line}
  334.        jnz @loop2       {go process the next byte}
  335.  
  336.      {ran against right edge of intrp window}
  337.      {so throw away rest of the scan data}
  338.      @loop3:            {suck up extra scan data}
  339.        dec dx           {did we run out of data?}
  340.        jz @done
  341.        lodsb            {get a frame scan byte}
  342.        shl al,1         {if it is not a sync, }
  343.        jnc @loop3       {keep looping}
  344.        jmp @loopd
  345.  
  346.      @loop4:            {fill out rest of intrp data}
  347.        and es:[di],ch   {strip old intrp value to 0}
  348.        inc di
  349.        dec bx           {loop until right edge reached}
  350.        jnz @loop4
  351.  
  352.      @loopd:
  353.        mov bx,ss:[IWidth]    {restore width to reg BX}
  354.        cmp di,ss:[Bottom]    {are we at bottom?}
  355.        jc @loop1             {do more if not at bottom}
  356.  
  357.      @done:
  358.        pop ds             {restore DS and we are done}
  359.      end;
  360.    end;
  361.  
  362.  
  363.  
  364. { ************************************************************** }
  365. { program start }
  366.  
  367. begin
  368.    cx := #55;
  369.  
  370.    directvideo := false;
  371.  
  372.    OldMode := CrtMode;
  373. (*   asm
  374.      mov ax,$0013    {switch to vga graphics mode}
  375.      mov bx,0
  376.      int $10
  377.    end;
  378.  
  379.    ib := 0;
  380.    while ib < 15 do
  381.    begin
  382.      asm
  383.        mov ax,1010h
  384.        mov ch,[ib]      {green}
  385.        add ch,ch
  386.        add ch,ch
  387.        mov cl,ch      {blue}
  388.        mov dh,ch      {red}
  389.        mov bl,[ib]
  390.        mov bh,0
  391.        int 10h
  392.      end;
  393.      inc(ib);
  394.    end;
  395. *)
  396.  
  397.  
  398.    Frame.Init;
  399.    if ParamCount > 0 then
  400.      Frame.SetFramePort(ParamStr(1))
  401.    else
  402.      Frame.SetFramePort('1');
  403.  
  404.   repeat
  405.  
  406.    if Frame.GrabOne then
  407.    begin
  408.       Frame.F2Iconvert(Frame.Framenum,Frame.GrabSize,
  409.                        Frame.IntrpWidth,Frame.IntrpSize,
  410.                        Frame.Iary, Frame.Fary[Frame.framenum]);
  411.    end;
  412.  
  413.    IntrpDisplay(Frame.framenum,Frame.IntrpWidth,Frame.IntrpSize,Frame.Iary);
  414.  
  415.    if keypressed then cx := readkey;
  416.   until cx < #32;
  417. (*
  418.    asm
  419.      mov ah,$00        {restore original display mode}
  420.      mov al,[oldmode]
  421.      mov bx,0
  422.      int $10
  423.    end;
  424. *)
  425. end.
  426.